#include "config.h"
#include "2socks.h"

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#if HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif

#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif

#if HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif

#include <stdarg.h>

extern struct global_options ts_opts;

void ts_log( const char * fmt, ... )
{
	va_list ap;

	va_start( ap, fmt );

	if( !ts_opts.verbosity ) {
		return;
	}
	vprintf( fmt, ap );
	va_end( ap );
}

void ts_log_socket( int fd, const char * desc )
{
	struct sockaddr_in addr;
	int len;
	len = sizeof addr;
	if( 0 > getsockname( fd, (struct sockaddr *) & addr, & len ) )
	{
		ts_log( "Error in getsockname: %d\n", fd );
		return;
	}
	ts_log( "%s: %s:%hu\n", desc, inet_ntoa( addr.sin_addr ), htons( addr.sin_port ) );
}

void ts_log_connection( int fd, const char * desc )
{
	struct sockaddr_in addr;
	int len;
#define IPADDRBUFLEN 16
	char myname[IPADDRBUFLEN];
	char hername[IPADDRBUFLEN];

	uint16_t myport;
	uint16_t herport;

	memset( myname, 0, sizeof myname );
	memset( hername, 0, sizeof hername );

	len = sizeof addr;
	if( 0 > getsockname( fd, (struct sockaddr *) & addr, & len ) )
	{
		ts_log( "Error in getsockname: %d\n", fd );
		return;
	}
	strncpy( myname, inet_ntoa( addr.sin_addr ), sizeof myname - 1);
	myport = ntohs( addr.sin_port );

	if( 0 > getpeername( fd, (struct sockaddr *) & addr, & len ) )
	{
		ts_log( "Error in getsockname: %d\n", fd );
		return;
	}
	strncpy( hername, inet_ntoa( addr.sin_addr ), sizeof hername - 1);
	herport = ntohs( addr.sin_port );

	ts_log( "%s: %s:%hu - %s:%hu\n", desc, myname, myport, hername, herport );
}

void ts_exit( int status, const char * fmt, ... )
{
	va_list ap;

	va_start( ap, fmt );
	fprintf( stderr, "Error: " );
	vfprintf( stderr, fmt, ap );
	fprintf( stderr, "\n" );
	va_end( ap );
	exit(status);
}
